package tm.testing;

import java.util.concurrent.Callable;

import javax.swing.ImageIcon;
 
import org.lex.input.StrategicHandler;
import org.lex.input.effects.HeightMap;
import org.lex.input.mouse.MouseManager;
import org.lex.input.mouse.component.CombinedMouse;
 
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.input.MouseInputListener;
import com.jme.intersection.TrianglePickResults;
import com.jme.light.DirectionalLight;
import com.jme.light.PointLight;
import com.jme.math.Ray;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.TextureManager;
import com.jmex.game.state.BasicGameState;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.FaultFractalHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;
 
public class ExampleGamestate extends BasicGameState implements MouseInputListener {
 
	private TerrainPage terrain;
	private Node geometry;
	private StrategicHandler strategicHandler;
	protected Camera cam;
	protected InputHandler input;
	protected LightState lightState;
 
	public ExampleGamestate(Camera camera) {
		super("Test");
		this.cam = camera;
		cam.setLocation( new Vector3f(0,0,0));
		init();
	}
 
	public void init(){
		/** Set up a basic, default light. */
        	PointLight light = new PointLight();
        	light.setDiffuse( new ColorRGBA( 0.75f, 0.75f, 0.75f, 0.75f ) );
        	light.setAmbient( new ColorRGBA( 0.5f, 0.5f, 0.5f, 1.0f ) );
        	light.setLocation( new Vector3f( 100, 100, 100 ) );
        	light.setEnabled( true );
 
		/** Attach the light to a lightState and the lightState to rootNode. */
        	lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
        	lightState.setEnabled( true );
        	lightState.attach( light );
        	rootNode.setRenderState( lightState );
 
		GameTaskQueueManager.getManager().update(new Callable<Object>() {
		    public Object call() throws Exception {
		    	setupTerrain();
		    	rootNode.updateRenderState();
		        return null;
		    }
		});
		setupHandler();
		rootNode.updateRenderState();
 
		KeyBindingManager.getKeyBindingManager().set( "exit", KeyInput.KEY_ESCAPE );
	}
 
	@Override
	public void update(float tpf) {
		super.update(tpf);
		strategicHandler.useCursor("default");
		input.update(tpf);
		if ( KeyBindingManager.getKeyBindingManager().isValidCommand( "exit", false ) ) {
			NextTest.getGame().finish();
		}
	}
 
	public void setupHandler() {
		HeightMap heightMap = new HeightMap() {
			public float getHeightAt(Vector3f location) {
				float height = terrain.getHeight(location);
				if (Float.isNaN(height)) height = 0;
				return height;
			}
		};
		MouseManager mouseManager = new MouseManager(CombinedMouse.get());
		strategicHandler = new StrategicHandler(cam, mouseManager, heightMap);
		input = strategicHandler;
 
		mouseManager.registerWithInputHandler(strategicHandler);
		mouseManager.setMousePosition(DisplaySystem.getDisplaySystem().getWidth()/2, DisplaySystem.getDisplaySystem().getHeight()/2);
		mouseManager.addListener(this);
		rootNode.attachChild(mouseManager.getMouse().getMouseSpatial());
	}
 
 
	public void setupTerrain() {
		geometry = new Node();
		rootNode.attachChild(geometry);
		Box box = new Box("WÜRFEL", new Vector3f(0,150,0), 50,50,50);
		box.setModelBound(new BoundingBox());
		box.updateModelBound();
		geometry.attachChild(box);
		
		
		
		Node terrainNode = new Node();
		rootNode.attachChild(terrainNode);
 
		// this piece is pretty much copied from the jme terrain test
 
		FaultFractalHeightMap heightMap = new FaultFractalHeightMap(257, 32, 0, 255, 0.75f);
		Vector3f terrainScale = new Vector3f(10,1,10);
		heightMap.setHeightScale( 0.001f);
		terrain = new TerrainPage("Terrain", 33,
	    		heightMap.getSize(), terrainScale,
	    		heightMap.getHeightMap());
 
		terrain.setDetailTexture(1, 16);
		terrainNode.attachChild(terrain);
 
		ProceduralTextureGenerator pt = new ProceduralTextureGenerator(heightMap);
		pt.addTexture(new ImageIcon(NextTest.class.getClassLoader().getResource(
       			"jmetest/data/texture/grassb.png")), -128, 0, 128);
		pt.addTexture(new ImageIcon(NextTest.class.getClassLoader().getResource(
        		"jmetest/data/texture/dirt.jpg")), 0, 128, 255);
		pt.addTexture(new ImageIcon(NextTest.class.getClassLoader().getResource(
        		"jmetest/data/texture/highest.jpg")), 128, 255, 384);
 
		pt.createTexture(512);
 
		TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
		ts.setEnabled(true);
		Texture t1 = TextureManager.loadTexture(
		        pt.getImageIcon().getImage(),
		        Texture.MinificationFilter.Trilinear, 
		        Texture.MagnificationFilter.Bilinear,
		        true);
		ts.setTexture(t1, 0);
 
		Texture t2 = TextureManager.loadTexture(
				NextTest.class.getClassLoader().getResource("jmetest/data/texture/Detail.jpg"),
			Texture.MinificationFilter.Trilinear, 
		       	Texture.MagnificationFilter.Bilinear);
 
		ts.setTexture(t2, 1);
		t2.setWrap(Texture.WrapMode.Repeat);
 
		t1.setApply(Texture.ApplyMode.Combine);
		t1.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
		t1.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
		t1.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
		t1.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
		t1.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
 
		t2.setApply(Texture.ApplyMode.Combine);
		t2.setCombineFuncRGB(Texture.CombinerFunctionRGB.AddSigned);
		t2.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
		t2.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
		t2.setCombineSrc1RGB(Texture.CombinerSource.Previous);
		t2.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
		t2.setCombineScaleRGB(Texture.CombinerScale.One);
 
		terrainNode.setRenderState(ts);
 
		FogState fs = DisplaySystem.getDisplaySystem().getRenderer().createFogState();
		fs.setDensity(0.5f);
		fs.setEnabled(true);
		fs.setColor(new ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f));
		fs.setEnd(1000);
		fs.setStart(500);
		fs.setDensityFunction(FogState.DensityFunction.Linear);
		fs.setQuality(FogState.Quality.PerVertex);
		terrainNode.setRenderState(fs);
 
		terrainNode.lock();
		terrainNode.lockBranch();
 
		CullState cs = DisplaySystem.getDisplaySystem().getRenderer().createCullState();
		cs.setCullFace(CullState.Face.Back);
		cs.setEnabled(true);
		terrainNode.setRenderState(cs);
 
		lightState.detachAll();
 
		DirectionalLight dl = new DirectionalLight();
		dl.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
		dl.setDirection(new Vector3f(1, -0.5f, 1));
		dl.setEnabled(true);
		lightState.attach(dl);
 
		DirectionalLight dr = new DirectionalLight();
		dr.setEnabled(true);
		dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
		dr.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
		dr.setDirection(new Vector3f(0.5f, -0.5f, 0).normalizeLocal());
		lightState.attach(dr);
	}

	public void onButton(int button, boolean pressed, int x, int y) {
		if(button==0 && pressed ==false) {
			processPick(x, y);
		}
	}

	public void onMove(int xDelta, int yDelta, int newX, int newY) {
		// TODO Auto-generated method stub
		
	}

	public void onWheel(int wheelDelta, int x, int y) {
		// TODO Auto-generated method stub
		
	}
	
	private void processPick(int x, int y) {
		System.out.println("PICK!");
    		
    	//mouseState.setMousePosition(new Coordinate(mouse_x, mouse_y));
    		
    	Vector2f screenPos = new Vector2f();
    	//Get the position that the mouse is pointing to
    	
		screenPos.set(x, y);
		System.out.println(screenPos.x + "AHA "+ screenPos.y);
		// Get the world location of that X,Y value
		Vector3f worldCoords = DisplaySystem.getDisplaySystem().getWorldCoordinates(screenPos, 1.0f);
		// Create a ray starting from the camera, and going in the direction
        // of the mouse's location
        final Ray mouseRay = new Ray(cam.getLocation(), worldCoords
                .subtractLocal(cam.getLocation()));
        mouseRay.getDirection().normalizeLocal();
        TrianglePickResults results = new TrianglePickResults();
        results.clear();
        results.setCheckDistance(true);
        geometry.findPick(mouseRay,results);
        
    
    	if(results.getNumber() > 0) {
    		System.out.println("VORHER: "+results.getNumber()+" AHA: "+results.getPickData(0).getTargetMesh().getName());
    	}
    	
	}
 
}